package com.baibei.ebec.sdk.interceptor;

import android.text.TextUtils;

import com.baibei.ebec.sdk.ApiConstant;
import com.baibei.ebec.sdk.RefreshTokenRequester;
import com.baibei.ebec.sdk.TokenInfo;
import com.baibei.sdk.ApiCode;
import com.baibei.sdk.ApiException;
import com.baibei.sdk.TokenEvent;
import com.blankj.utilcode.utils.LogUtils;
import com.rae.swift.session.SessionManager;
import com.squareup.okhttp3.interceptor.TokenInterceptor;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONObject;

import java.io.IOException;

import okhttp3.Request;
import okhttp3.Response;

/**
 * Token 自动续期拦截器
 * Created by ChenRui on 2017/4/27 0027 14:06.
 */
public class ApiTokenInterceptor extends TokenInterceptor {

    private SessionManager mSessionManager;
    private RefreshTokenRequester mRefreshTokenRequester;

    public ApiTokenInterceptor() {
        mSessionManager = SessionManager.getDefault();
        mRefreshTokenRequester = new RefreshTokenRequester();
    }

    public int mRetryCount; // 刷新TOKEN重试次数

    /**
     * TOKEN 重试次数
     */
    public static int TOKEN_RETRY_COUNT = 3;

    @Override
    public Response intercept(Chain chain) throws IOException {

        Response response = super.intercept(chain);

        // 保存下发的token
        String accessToken = response.header(ApiConstant.ACCESS_TOKEN_KEY);
        String refreshToken = response.header(ApiConstant.REFRESH_TOKEN_KEY);

        if (!TextUtils.isEmpty(accessToken) && !TextUtils.isEmpty(refreshToken)) {
            // 保存Token
            mSessionManager.setUserToken(new TokenInfo(accessToken, refreshToken));
            mRetryCount = 0;
        }


        return response;
    }

    @Override
    protected boolean invalidateToken(Request request, Response response, String body) throws Exception {


        // 解析返回错误码
        JSONObject object = new JSONObject(body);

        // 刷新的Token是返回在BODY中
        String code = object.has("code") ? object.getString("code") : null;

        // 下发的TOKEN
        if (TextUtils.equals(ApiCode.SUCCESS, code) && object.has("accessToken")) {
            // 更新AccessToken
            TokenInfo tokenInfo = mSessionManager.getUserToken();
            if (tokenInfo == null)
                tokenInfo = new TokenInfo();
            tokenInfo.setAccessToken(object.getString("accessToken"));
            mSessionManager.setUserToken(tokenInfo);
        }

        boolean result = ApiCode.ACCESS_TOKEN_EXPIRED.equalsIgnoreCase(code) && request.header("API_REFRESH_TOKEN") == null;

        if (result) {
            mRetryCount++;
            LogUtils.w("api", "TOKEN 过期:" + request.url() + "\n" + body);
        }
        return result;
    }

    @Override
    protected String refreshToken(String body) throws IOException {
        // 超过重试次数
        if (mRetryCount > TOKEN_RETRY_COUNT) {
            mRetryCount = 0;
            return notifyTokenException();

        }

        LogUtils.i("api", "TOKEN 过期，准备刷新..");
        TokenInfo tokenInfo = mSessionManager.getUserToken();


        if (tokenInfo == null || TextUtils.isEmpty(tokenInfo.getRefreshToken())) {
            LogUtils.e("api", "TOKEN刷新失败，用户信息或者Token信息为空！");
            return notifyTokenException();
        }

        // 刷新Token
        LogUtils.i("api", "开始刷新Token,RefreshToken = " + tokenInfo.getRefreshToken());
        mRefreshTokenRequester.refresh(tokenInfo.getRefreshToken());
        tokenInfo = mSessionManager.getUserToken();
        if (tokenInfo == null || TextUtils.isEmpty(tokenInfo.getRefreshToken())) {
            LogUtils.e("api", "TOKEN刷新失败，接口返回的信息为空！");
            return notifyTokenException();
        }

        LogUtils.i("api", "刷新Token成功： " + tokenInfo);

        return tokenInfo.getAccessToken();
    }

    private String notifyTokenException() throws ApiException {
        // 清除用户缓存
        SessionManager.getDefault().clear();
//        ApiConstant.APP_U_KEY_VALUE = null;

        // 发送事件
        EventBus.getDefault().post(new TokenEvent());
        throw new ApiException("登录过期");
    }


    @Override
    protected void retryRequest(Request.Builder builder, String token) throws IOException {
        builder.removeHeader(ApiConstant.ACCESS_TOKEN_KEY).addHeader(ApiConstant.ACCESS_TOKEN_KEY, token);
    }

}
